// Header Protection
#ifndef _REGISTRATION_H_
#define _REGISTRATION_H_

// Include Files
#include "Notification.h"

// Namespace
namespace IE
{
	/////////////////////////////////////////////////////////////////////////////////
	// A registration is created whenever a listener begins listening for an event, 
	//     it provides the link between the event and the listener.
	class ABCRegistration
	{
	public:     // methods
		inline ABCRegistration() { }
		inline virtual ~ABCRegistration() = 0 { }

		// The event was raised, send it to the derived class to get the listener 
		//     and handler.
		// _pArg : CEventArg * - the event argument
		inline virtual void Raise( CEventArg *_pArg ) = 0;

	protected:  // child methods

		// The event was raised, create a new notification and and send it to the 
		//     listener.
		// _pListener : listener_t * - the listener for the event
		// _pArg : eventarg_t * - the event argument given when the event was raised
		// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler in the 
		//     listener for the event.
		template< class listener_t, class eventarg_t >
		inline void Raise( listener_t *_pListener, 
			eventarg_t *_pArg, void (listener_t::*_pHandler)(eventarg_t &) )
		{
			_pListener->Raise( 
				new CNotification<listener_t, eventarg_t>(_pArg, _pHandler) );
		}

	private:    // dummy definitions

		ABCRegistration( ABCRegistration const & );
		ABCRegistration &operator =( ABCRegistration const & );
	};

	/////////////////////////////////////////////////////////////////////////////////
	// A registration for a specific type of listener and event argument.
	// listener_t : template - the type of the listener for the event
	// eventarg_t : template - the type of the event argument
	template< class listener_t, class eventarg_t >
	class CRegistration : public ABCRegistration
	{
	public:     // methods

		// _pListener : listener_t * - the listener which is registered for the event
		// _pHandler : void (listener_t::*)(eventarg_t &) - the event handler for 
		//     the event in the listener.
		inline CRegistration( 
			listener_t *_pListener, void (listener_t::*_pHandler)(eventarg_t &) ) :
		m_pListener(_pListener), m_pHandler(_pHandler)
		{ }

		// The event was raised, raise it in the listener by calling the base class.
		// _pArg : CEventArg * - the event argument
		inline void Raise( CEventArg *_pArg )
		{
			ABCRegistration::Raise( m_pListener, (eventarg_t*)_pArg, m_pHandler );
		}

	private:    // CEvent<eventarg_t> friend methods
		friend CEvent<eventarg_t>;

		inline listener_t const *GetListener() const { return m_pListener; }

		inline void( listener_t::* const GetHandler() const )(eventarg_t &)
		{ return m_pHandler; }

	private:    // data
		listener_t *m_pListener;
		void (listener_t::*m_pHandler)(eventarg_t &);
	};
}

// Header Protection
#endif // _REGISTRATION_H_
